package com.example.ttt.utils;

import com.aliyun.oss.*;
import com.aliyun.oss.common.comm.Protocol;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.OSSObjectSummary;
import com.aliyun.oss.model.ObjectListing;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

/*
* OSS客户端的目录结构
* adjoinMe(小写)
*   music
*       user_file
* */

@Component
@Slf4j
public class OSSClient {

    @Autowired
    private Environment environment;

    private OSS ossClient;

    // 初始化OSSClient
    public void OSSInit(){
        /*
         * yourEndpoint填写Bucket所在地域对应的Endpoint。
         * 以华东1（杭州）为例Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
         * 阿里云账号AccessKey拥有所有API的访问权限，风险很高。
         * 强烈建议您创建并使用RAM用户进行API访问或日常运维，请登录RAM控制台创建RAM用户。
         * */
        String endpoint = environment.getProperty("oss.endpoint");
        String accessKeyId = environment.getProperty("oss.accessKeyId");
        String accessKeySecret = environment.getProperty("oss.accessKeySecret");

        /*
         * 创建ClientConfiguration。ClientConfiguration是OSSClient的配置类.
         * 可配置代理、连接超时、最大连接数等参数。
         * */
        ClientBuilderConfiguration conf = new ClientBuilderConfiguration();
        // 设置OSSClient允许打开的最大HTTP连接数，默认为1024个。
        conf.setMaxConnections(200);
        // 设置Socket层传输数据的超时时间，默认为50000毫秒。
        conf.setSocketTimeout(10000);
        // 设置建立连接的超时时间，默认为50000毫秒。
        conf.setConnectionTimeout(10000);
        // 设置从连接池中获取连接的超时时间（单位：毫秒），默认不超时。
        conf.setConnectionRequestTimeout(1000);
        // 设置连接空闲超时时间。超时则关闭连接，默认为60000毫秒。
        conf.setIdleConnectionTime(10000);
        // 设置失败请求重试次数，默认为3次。
        conf.setMaxErrorRetry(5);
        // 设置是否支持将自定义域名作为Endpoint，默认支持。
        conf.setSupportCname(true);
        // 设置是否开启二级域名的访问方式，默认不开启。
        conf.setSLDEnabled(true);
        // 设置连接OSS所使用的协议（HTTP或HTTPS），默认为HTTP。
        conf.setProtocol(Protocol.HTTP);
        // 设置用户代理，指HTTP的User-Agent头，默认为aliyun-sdk-java。
        conf.setUserAgent("aliyun-sdk-java");
        // 设置代理服务器端口。
        conf.setProxyHost("<yourProxyHost>");
        // 设置代理服务器验证的用户名。
        conf.setProxyUsername("<yourProxyUserName>");
        // 设置代理服务器验证的密码。
        conf.setProxyPassword("<yourProxyPassword>");
        // 设置是否开启HTTP重定向，默认开启。
        conf.setRedirectEnable(true);
        // 设置是否开启SSL证书校验，默认开启。
        conf.setVerifySSLEnable(true);

        /*
         * 创建OSSClient实例。
         * 关闭OSSClient。
         * */
        ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        // ossClient.shutdown();
    }

    /*
     * 上传文件到OSS
     * Bucket名称，例如examplebucket
     * 填写Object完整路径，例如exampledir/exampleobject.txt。Object完整路径中不能包含Bucket名称。
     * content
     * */
    public void uploadOSS(String bucketName, String objectName, FileInputStream fileInputStream) {

        try {
            ossClient.putObject(bucketName, objectName, fileInputStream);
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    /*
     * 下载文件
     * bucketName    Bucket名称，例如examplebucket
     * folder        文件资源远程路径
     * objectName    文件名称
     * downPath      文件下载地址的目录
     * */
    public void downOSS(String bucketName, String folder, String objectName, String downFolder) {

        OSSObject object = ossClient.getObject(bucketName, folder + "/" + objectName);
        InputStream objectContent = object.getObjectContent();
        // 拼接下载地址路径
        String downloadFile = downFolder + "\\" + objectName;

        try {
            File file = new File(downloadFile);
            FileUtils.copyInputStreamToFile(objectContent, file);
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    /*
    * 获取文件目录
    * objectListing.getObjectSummaries获取所有文件的描述信息。
    * */
    public ArrayList<String> getObjectList(String bucketName){

        List<OSSObjectSummary> objectSummaries = null;
        try {
            ObjectListing objectListing = ossClient.listObjects(bucketName);
            objectSummaries = objectListing.getObjectSummaries();
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }

        // 处理返回结果
        ArrayList<String> returnArray = new ArrayList<>();
        for (int i = 0; i < objectSummaries.size(); i++) {
            returnArray.add(objectSummaries.get(i).getKey());
        }
        return returnArray;
    }
}
